home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / tcp / wu_ftpd_37_21.lha / wu-ftpd / src / ftw.c < prev    next >
C/C++ Source or Header  |  1994-08-08  |  7KB  |  373 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #if defined(LIBC_SCCS) && !defined(lint)
  19. static char sccsid[] = "@(#)ftw.c    5.3 (Berkeley) 8/5/88";
  20.  
  21. #endif /* LIBC_SCCS and not lint */
  22.  
  23. #ifndef AMIGA
  24. #include "../src/config.h"
  25. #else
  26. #include "config.h"
  27. #endif
  28.  
  29. #ifdef HAVE_DIRENT
  30. #include <dirent.h>
  31. #else
  32. #include <sys/dir.h>
  33. #endif
  34.  
  35. #include <errno.h>
  36.  
  37. #include <sys/param.h>
  38. #include <sys/stat.h>
  39. #include <sys/stat.h>
  40.  
  41. #ifdef AMIGA
  42. #include <bsdsocket.h>
  43. #endif
  44.  
  45. #include "ftw.h"
  46.  
  47. #define    NODESC    -1
  48.  
  49. #ifdef HAVE_SYMLINK
  50. # define    ISLINK(sb)    ((sb.st_mode&S_IFMT) == S_IFLNK)
  51. #else
  52. # define lstat stat
  53. #endif
  54.  
  55. #define    ISDIR(sb)    ((sb.st_mode&S_IFMT) == S_IFDIR)
  56. #define    ISDOT(dp) \
  57.     (dp->d_name[0] == '.' && (!dp->d_name[1] || \
  58.         (dp->d_name[1] == '.' && !dp->d_name[2])))
  59.  
  60. extern int errno;
  61. static int g_fds,
  62.   (*g_fn) (),
  63.   g_opts;
  64. static char *bp;
  65.  
  66. int treewalk(char *path, int (*fn) ( /* ??? */ ), int maxfds, int opts);
  67.  
  68. /*
  69.  * cycle through the directories at the top of the tree, otherwise, once
  70.  * you run out of descriptors you have to keep reusing the same one and
  71.  * it gets *real* slow.
  72.  */
  73. typedef struct d_fd {
  74.     struct d_fd *next;
  75.     DIR *dirp;
  76.     off_t off;
  77. } FD;
  78.  
  79. static FD *freep,
  80.  *node;
  81.  
  82. static int
  83. walk(register char *name)
  84. {
  85. #ifdef HAVE_DIRENT
  86.     register struct dirent *dp;
  87. #else
  88.     register struct direct *dp;
  89. #endif
  90.     register int rval;
  91.     struct stat sb;
  92.     FD cur;
  93.     char *save,
  94.      *strcpy(char *, const char *);
  95.  
  96.     if (!freep)
  97.         freep = &cur;
  98.     else
  99.         node->next = &cur;
  100.     node = &cur;
  101.     cur.off = 0;
  102.  
  103.   getfd:if (!g_fds) {
  104.         freep->off = telldir(freep->dirp);
  105.         closedir(freep->dirp);
  106.         freep = freep->next;
  107.         ++g_fds;
  108.     }
  109.     if ( !(cur.dirp = opendir(bp)) ) {
  110.         if (errno == EMFILE) {
  111.             g_fds = 0;
  112.             goto getfd;
  113.         }
  114.         return (errno == EACCES ? (*g_fn) (bp, &sb, FTW_DNR) : -1);
  115.     } else
  116.         --g_fds;
  117.  
  118.     for (; *name; ++name) ;
  119.     *name++ = '/';
  120.     for (rval = 0, dp = readdir(cur.dirp); dp; dp = readdir(cur.dirp)) {
  121.         if (ISDOT(dp))
  122.             continue;
  123.         (void) strcpy(name, dp->d_name);
  124.         if (lstat(bp, &sb)) {
  125.             rval = errno == EACCES ?
  126.                 (*g_fn) (bp, &sb, FTW_NS) : -1;
  127.             if (rval)
  128.                 break;
  129.         }
  130. #ifdef HAVE_SYMLINK
  131.         if (ISLINK(sb) && g_opts & FTW_SYMLINK)
  132.             if (stat(bp, &sb))
  133.                 continue;
  134. #endif
  135.         if (!ISDIR(sb)) {
  136.             rval = (*g_fn) (bp, &sb, FTW_F);
  137.             if (rval)
  138.                 break;
  139.             continue;
  140.         }
  141.         if (g_opts & FTW_DIRLAST)
  142. #ifdef HAVE_D_NAMLEN
  143.             save = name + dp->d_namlen;
  144. #else
  145.             save = name + strlen(dp->d_name);
  146. #endif
  147.         rval = (*g_fn) (bp, &sb, FTW_D);
  148.         if ( (rval && rval != NODESC) || (rval = walk(name)))
  149.             break;
  150.         if (g_opts & FTW_DIRLAST) {
  151.             *save = '\0';
  152.             rval = (*g_fn) (dp->d_name, &sb, FTW_D2);
  153.             if (rval)
  154.                 if (rval == NODESC)
  155.                     rval = 0;
  156.                 else
  157.                     break;
  158.         }
  159.         if (cur.off) {
  160.             *name = NULL;
  161.             if ( (cur.dirp = opendir(bp)) ) {
  162.                 seekdir(cur.dirp, cur.off);
  163.                 /* tricky; if we have to reset the directory pointer we know
  164.                  * it's the next one to reuse */
  165.                 freep = &cur;
  166.                 --g_fds;
  167.             }
  168.             /* directory moved from under us!!! */
  169.             else {
  170.                 rval = -1;
  171.                 break;
  172.             }
  173.         }
  174.     }
  175.     closedir(cur.dirp);
  176.     ++g_fds;
  177.     return (rval);
  178. }
  179.  
  180. static int
  181. chwalk(register char *name)
  182. {
  183. #ifdef HAVE_DIRENT
  184.     register struct dirent *dp;
  185. #else
  186.     register struct direct *dp;
  187. #endif
  188.  
  189.     register int rval;
  190.     struct stat sb;
  191.     FD cur;
  192.     char *pwd,
  193. #ifndef HAVE_GETCWD
  194.      *getwd(char *),
  195. #endif
  196. #ifndef NO_MALLOC_PROTO
  197.      *malloc(size_t),
  198. #endif
  199.      *strcpy(char *, const char *);
  200.  
  201.     if (!freep)
  202.         freep = &cur;
  203.     else
  204.         node->next = &cur;
  205.     node = &cur;
  206.     cur.off = 0;
  207.  
  208.     if (chdir(name))
  209.         return (errno == EACCES ? (*g_fn) (name, &sb, FTW_DNR) : -1);
  210.  
  211.   getfd:if (!g_fds) {
  212.         freep->off = telldir(freep->dirp);
  213.         closedir(freep->dirp);
  214.         freep = freep->next;
  215.         ++g_fds;
  216.     }
  217.     if ( !(cur.dirp = opendir(".")) )  {
  218.         if (errno == EMFILE) {
  219.             g_fds = 0;
  220.             goto getfd;
  221.         }
  222.         return (errno == EACCES ? (*g_fn) (".", &sb, FTW_DNR) : -1);
  223.     } else
  224.         --g_fds;
  225.  
  226.     for (rval = 0, dp = readdir(cur.dirp); dp; dp = readdir(cur.dirp)) {
  227.         if (ISDOT(dp))
  228.             continue;
  229.         if (lstat(dp->d_name, &sb)) {
  230.             rval = errno == EACCES ?
  231.                 (*g_fn) (dp->d_name, &sb, FTW_NS) : -1;
  232.             if (rval)
  233.                 break;
  234.         }
  235.         pwd = NULL;
  236. #ifdef HAVE_SYMLINK
  237.         if (ISLINK(sb) && g_opts & FTW_SYMLINK) {
  238.             if (stat(dp->d_name, &sb))
  239.                 continue;
  240.             if (ISDIR(sb)) {
  241.                 /* NOSTRICT */
  242.                 if (!(pwd = malloc((u_int) MAXPATHLEN))) {
  243.                     rval = -1;
  244.                     break;
  245.                 }
  246. #ifdef HAVE_GETCWD
  247.                 if (!getcwd(pwd,MAXPATHLEN)) {
  248. #else
  249.                 if (!getwd(pwd)) {
  250. #endif
  251.                     rval = -1;
  252.                     break;
  253.                 }
  254.             }
  255.         }
  256. #endif
  257.         if (!ISDIR(sb)) {
  258.             rval = (*g_fn) (dp->d_name, &sb, FTW_F);
  259.             if (rval)
  260.                 break;
  261.             continue;
  262.         }
  263.         rval = (*g_fn) (dp->d_name, &sb, FTW_D);
  264.         if ((rval && rval != NODESC) || (rval = chwalk(dp->d_name)))
  265.             break;
  266.         if (g_opts & FTW_DIRLAST) {
  267.             rval = (*g_fn) (dp->d_name, &sb, FTW_D2);
  268.             if (rval)
  269.                 if (rval == NODESC)
  270.                     rval = 0;
  271.                 else
  272.                     break;
  273.         }
  274.         if (pwd && chdir(pwd)) {
  275.             rval = -1;
  276.             break;
  277.         }
  278.         if (cur.off) {
  279.             if ( (cur.dirp = opendir(".")) ) {
  280.                 seekdir(cur.dirp, cur.off);
  281.                 /* tricky; if we have to reset the directory pointer we know
  282.                  * it's the next one to reuse */
  283.                 freep = &cur;
  284.                 --g_fds;
  285.             }
  286.             /* directory moved from under us!!! */
  287.             else {
  288.                 rval = -1;
  289.                 break;
  290.             }
  291.         }
  292.     }
  293.     closedir(cur.dirp);
  294.     ++g_fds;
  295.     if (chdir(".."))
  296.         return (-1);
  297.     return (rval);
  298. }
  299.  
  300. /* S5 compatible ftw(BA_LIB) */
  301. int
  302. ftw(char *path, int (*fn) ( /* ??? */ ), int maxfds)
  303. {
  304.     return (treewalk(path, fn, maxfds, 0));
  305. }
  306.  
  307. int
  308. treewalk(char *path, int (*fn) ( /* ??? */ ), int maxfds, int opts)
  309. {
  310.     struct stat sb;
  311.     int rval;
  312.     char *pwd,
  313. #ifndef HAVE_GETCWD
  314.      *getwd(char *),
  315. #endif
  316. #ifndef NO_MALLOC_PROTO
  317.      *malloc(size_t),
  318. #endif
  319.      *strcpy(char *, const char *);
  320.  
  321.     if (lstat(path, &sb))
  322.         return (errno == EACCES ? (*fn) (path, &sb, FTW_NS) : -1);
  323.  
  324.     pwd = NULL;
  325. #ifdef HAVE_SYMLINK
  326.     if (ISLINK(sb) && opts & FTW_SYMLINK) {
  327.         if (stat(path, &sb))
  328.             return (0);
  329.         if (ISDIR(sb)) {
  330.             /* NOSTRICT */
  331.             if (!(pwd = malloc((u_int) MAXPATHLEN)))
  332.                 return (-1);
  333. #ifdef HAVE_GETCWD
  334.             if (!getcwd(pwd,MAXPATHLEN))
  335. #else
  336.             if (!getwd(pwd))
  337. #endif
  338.                 return (-1);
  339.         }
  340.     }
  341. #endif
  342.     if (!ISDIR(sb))
  343.         return ((*fn) (path, &sb, FTW_F));
  344.  
  345.     if (!maxfds)
  346.         return (-1);
  347.     g_fds = maxfds == -1 ? getdtablesize(): maxfds;
  348.     g_fn = fn;
  349.     g_opts = opts;
  350.  
  351.     if (!(opts & FTW_CHDIR) && !(bp = malloc((u_int) MAXPATHLEN))) {
  352.         errno = ENOMEM;
  353.         return (-1);
  354.     }
  355.     rval = (*fn) (path, &sb, FTW_D);
  356.     if (rval == NODESC)
  357.         rval = 0;
  358.     else if (!rval) {
  359.         if (opts & FTW_CHDIR)
  360.             rval = chwalk(path);
  361.         else
  362.             rval = walk(strcpy(bp, path));
  363.         if (!rval && opts & FTW_DIRLAST) {
  364.             rval = (*fn) (path, &sb, FTW_D2);
  365.             if (rval == NODESC)
  366.                 rval = 0;
  367.         }
  368.     }
  369.     if (pwd && chdir(pwd))
  370.         return (-1);
  371.     return (rval);
  372. }
  373.